<?php

namespace app\api\services\store;

use app\api\model\Coupon;
use app\api\model\CouponUser;
use app\api\model\Goods;
use app\api\model\GoodsCart;
use app\api\model\GoodsProduct;
use app\api\model\UserAddress;
use app\api\services\BaseServices;
use app\api\services\user\AddressServices;
use app\api\util\Date;
use app\api\util\Laravel;
use Carbon\Carbon;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\exception\DbException;
use think\Model;

class CartServices extends BaseServices
{
    /**
     * 更新购物车
     * @param $cartProduct
     * @param $product
     * @param $number
     * @throws Exception
     */
    private function editCart($cartProduct, $product, $number)
    {
        if ($number > $product['number']) {
            throw new Exception("库存不足");
        }
        try {
            $cartProduct->number = $number;
            $cartProduct->save();
            return $cartProduct;
        } catch (Exception $e) {
            throw new Exception("更新购物车失败");
        }
    }

    /**
     * 新增购物车
     * @param $userid
     * @param $goods
     * @param $product
     * @param $number
     * @param $join_merchant_id
     * @return GoodsCart
     * @throws Exception
     */
    private function newCart($userid, $goods, $product, $number, $join_merchant_id, $type = 1)
    {
        if ($number > $product['number']) {
            throw new Exception("库存不足");
        }

        try {
            $cart = new GoodsCart();
            $cart->user_id = $userid;
            $cart->merchant_id = $join_merchant_id;
            $cart->store_goods_id = $goods['id'];
            $cart->goods_sn = $goods['goods_sn'];
            $cart->goods_name = $goods['name'];
            $cart->product_id = $product['id'];
            $cart->type = $type;
            $cart->price = $product['price'];
            $cart->number = $number;
            $cart->specifications = $product['specifications'];
            $cart->pic_url = $product['url'] ?? "";
            $cart->save();
            return $cart;
        } catch (Exception $e) {
            throw new Exception("添加购物车失败");
        }
    }

    /**
     * 获取用户购物车商品
     * @param $userid
     * @param $goods_id
     * @param $product_id
     * @return array|bool|\PDOStatement|string|Model|null
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    private function getCartProduct($userid, $goods_id, $product_id)
    {
        return GoodsCart::where('user_id', $userid)
            ->where('store_goods_id', $goods_id)
            ->where('product_id', $product_id)
            ->find();
    }

    /**
     * 新增购物车
     * @param $userid
     * @param $goods_id
     * @param $product_id
     * @param $number
     * @param $join_merchant_id
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws Exception
     * @throws ModelNotFoundException
     */
    public function add($userid, $goods_id, $product_id, $number, $join_merchant_id)
    {
        list($goods, $product) = self::getGoodsInfo($goods_id, $product_id);
        $cartProduct = self::getCartProduct($userid, $goods_id, $product_id);
        if (empty($cartProduct)) {
            // 创建购物车
            self::newCart($userid, $goods, $product, $number, $join_merchant_id);
        } else {
            // 增加购物车数量
            $number = $cartProduct['number'] + $number;
            self::editCart($cartProduct, $product, $number);
        }
    }

    /**
     * 获取商品和货品
     * @param $goods_id
     * @param $product_id
     * @return array
     * @throws Exception
     */
    public function getGoodsInfo($goods_id, $product_id): array
    {
        $goods = Goods::getById($goods_id);
        if (empty($goods) || $goods->is_on_sale == '0') {
            throw new Exception("商品已下架");
        }
        $product = GoodsProduct::getById($product_id);
        if (empty($product)) {
            throw new Exception("货品不存在");
        }
        return [$goods, $product];
    }

    /**
     * 立即购买
     * @param $id
     * @param $goods_id
     * @param $product_id
     * @param $number
     * @param $join_merchant_id
     * @return GoodsCart
     * @throws DataNotFoundException
     * @throws DbException
     * @throws Exception
     * @throws ModelNotFoundException
     */
    public function fastAdd($id, $goods_id, $product_id, $number, $join_merchant_id): GoodsCart
    {
        list($goods, $product) = self::getGoodsInfo($goods_id, $product_id);
        $cartProduct = self::getCartProduct($id, $goods_id, $product_id);
        return self::newCart($id, $goods, $product, $number, $join_merchant_id, 2);

    }

    /**
     * 获取未过期的购物车列表
     * @param $userid
     * @return bool|\PDOStatement|string|Collection
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getValidCartList($userid)
    {
        $list = GoodsCart::getCartList($userid);
        $list = (new Collection($list))->toArray();
        $goodsIds = array_column($list, 'store_goods_id');
        $goodsList = GoodsServices::getGoodsByIds($goodsIds);
        $goodsList = (new Collection($goodsList))->toArray();
        $goodsList = Laravel::keyBy($goodsList, 'id');
        $invalidCartIds = [];// 过期的购物车商品id

        $list = array_filter($list, function ($item) use ($goodsList, &$invalidCartIds) {
            $goods = $goodsList[$item['store_goods_id']] ?? [];
            $isValid = $goods['is_on_sale'] == '1' && !empty($goods);
            if (!$isValid) {
                $invalidCartIds[] = $item['id'];
            }
            return $isValid;
        });
        self::deleteCartList($invalidCartIds);
        return $list;
    }

    /**
     * 购物车列表
     * @param $userid
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function list($userid): array
    {
        $list = self::getValidCartList($userid);
        $goodsCount = 0;
        $goodsAmount = 0;
        $checkedGoodsCount = 0;
        $checkedGoodsAmount = 0;
        foreach ($list as $item) {
            $goodsCount = bcadd($goodsCount, $item['number']);
            $amount = bcmul($item['price'], $item['number'], 2);
            $goodsAmount = bcadd($goodsAmount, $amount, 2);
            if ($item['checked']) {
                $checkedGoodsCount = bcadd($checkedGoodsCount, $item['number']);
                $checkedGoodsAmount = bcadd($checkedGoodsAmount, $amount, 2);
            }
        }
        GoodsCart::decorationMerchant($list);
        $list = Laravel::groupBy($list, 'merchant');
        $result = [];
        foreach ($list as $k => $item) {
            $result[] = ['name' => $k, 'merchant_id' => $item[0]['merchant_id'], 'valueList' => $item];
        }
        return [
            'cartList' => $result,
            'cartTotal' => [
                'goodsCount' => $goodsCount,
                'goodsAmount' => (double)$goodsAmount,
                'checkedGoodsCount' => $checkedGoodsCount,
                'checkedGoodsAmount' => (double)$checkedGoodsAmount
            ]
        ];
    }

    /**
     * 删除过期的购物车
     * @param $ids
     * @return false|int
     */
    public function deleteCartList($ids)
    {
        if (empty($ids)) {
            return 0;
        }
        return GoodsCart::where('id', 'in', $ids)->delete();
    }

    /**
     * 更新
     * @param $userid
     * @param $id
     * @param $goodsId
     * @param $productId
     * @param $number
     * @return void
     * @throws Exception
     */
    public function update($userid, $id, $goodsId, $productId, $number)
    {
        $cart = GoodsCart::getCartById($id, $userid);
        if (empty($cart)) {
            throw new Exception("购物车不存在");
        }
        if ($cart['store_goods_id'] != $goodsId || $cart['product_id'] != $productId) {
            throw new Exception("商品信息错误");
        }
        $goods = Goods::getById($goodsId);
        if (empty($goods) || $goods->is_on_sale != '1') {
            throw new Exception("商品已下架");
        }
        $product = GoodsProduct::getById($productId);
        if (empty($product) || $product['number'] < $number) {
            throw new Exception("库存不足");
        }
        $cart->number = $number;
        $ret = $cart->save();
        if (!$ret) {
            throw new Exception("更新失败");
        }
    }

    /**
     * 获取当前适合的优惠券
     * @param $userid
     * @param $price
     * @return bool|\PDOStatement|string|Collection
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getMeetPriceCouponAndSort($userid, $price)
    {
        $couponUsers = CouponUser::getUsableCoupons($userid, ['coupon']);
        $couponUsers = (new Collection($couponUsers))->toArray();
        $couponIds = array_column($couponUsers, 'coupon_id');
        $coupons = Coupon::where('id', 'in', $couponIds)->select();
        $coupons = (new Collection($coupons))->toArray();
        $coupons = Laravel::keyBy($coupons, 'id');
        return array_filter($couponUsers, function ($couponUser) use ($coupons, $price) {
            $coupon = $coupons[$couponUser['coupon_id']];
            return self::checkCouponAndPrice($coupon, $couponUser, $price);
        });

    }

    public function coupons($userid, $price)
    {
        return self::getMeetPriceCouponAndSort($userid, $price);


    }

    public function checkCouponAndPrice($coupon, $couponUser, $price): bool
    {
        if (empty($coupon)) {
            return false;
        }
        if (empty($couponUser)) {
            return false;
        }
        if ($couponUser['coupon_id'] != $coupon['id']) {
            return false;
        }
        if ($coupon['status'] != 0) {
            return false;
        }

        if ($coupon['coupon_type'] == 3) {
            return false;
        }
        // 最低消费不能大于商品价格
        if (bccomp($coupon['mini_price'], $price) == 1) {
            return false;
        }
        $now = Carbon::now();
        switch ($coupon['usage_type']) {
            case '2':
                $start = Carbon::parse($coupon['useage_start_time']);
                $end = Carbon::parse($coupon['useage_end_time']);
                if ($now->isBefore($start) || $now->isAfter($end)) {
                    return false;
                }
                break;
            case '1':
                $expired = Carbon::parse($couponUser['createtime'])->addDays($coupon['useage_day']);
                if ($now->isAfter($expired)) {
                    return false;
                }
                break;
            default:
                return false;

        }
        return true;

    }

    /**
     * 下单前信息确认
     * @param $userid
     * @param $cartIds
     * @param $addressId
     * @param $couponId
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws Exception
     * @throws ModelNotFoundException
     */
    public function checkout($userid, $cartIds, $addressId, $couponId): array
    {
        // 如果用在商品确认页面点击新增商品数量，先调用更新购物车商品数量的方法，再调用一下此方法
        // 删除已过期的商品
        $cartList = GoodsCart::getCartByIds($userid, $cartIds);
        if (empty($cartList)) {
            throw new Exception("购物车数据为空");
        }
        $address = AddressServices::getInstance()->getByIdOrDefaultAddress($userid, $addressId);

        $countPrice = 0;
        $goodsPriceList = [];
        foreach ($cartList as $c) {
            $countPrice = bcadd($countPrice, bcmul($c['price'], $c['number'], 2), 2);
            $goodsPriceList[] = [
                'name' => $c['goods_name'],
                'price' => bcmul($c['price'], $c['number'], 2)
            ];
        }
        $couponList = [];

        $couponUsers = self::getMeetPriceCouponAndSort($userid, $countPrice);
        $availabelCouponLength = count($couponUsers);
        if (is_null($couponId) || $couponId == -1) {
            $couponList = [];
        }
        if (!empty($couponId)) {
            $coupon = Coupon::where('id', $couponId)->find();
            $couponUser = CouponUser::getUserCoupon($userid, $couponId);
            $is = self::checkCouponAndPrice($coupon, $couponUser, $countPrice);
            if ($is) {
                $couponList = $couponUser;
            }
        } else {
            $couponList = $couponUsers[0] ?? [];
        }
        $couponId = -1;
        $userCouponId = -1;
        $couponPrice = 0;
        if (!empty($couponList)) {
            $couponId = $couponList['coupon_id'];
            $userCouponId = $couponList['id'];
            $couponPrice = Coupon::find($couponId)['coupon_price'] ?? 0;
            $countPrice = bcsub($countPrice, $couponPrice, 2);
            if ($countPrice <= 0) {
                $countPrice = 0;
            }
        }
        return [
            'cartList' => $cartList,
            'countPrice' => $countPrice,
            'goodsPriceList' => $goodsPriceList,
            'address' => $address,
            'couponList' => $couponList,
            'couponId' => $couponId,
            'userCouponId' => $userCouponId,
            'couponPrice' => $couponPrice,
            'availabelCouponLength' => $availabelCouponLength
        ];
    }

    /**
     * 获取已选择的购物车商品列表
     * @param int $userid
     * @param $cartId
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     * @throws \Exception
     */
    public function getCheckedCartLists(int $userid, $cartId)
    {
        $cartId = (array)$cartId;
        if (empty($cartId)) {
            $cartList = GoodsCart::where('user_id', $userid)->with('product')->where('checked', 1)->select();
        } else {
            $cart = GoodsCart::whereIn('id', $cartId)->with('product')->where('user_id', $userid)->select();
            if (empty($cart)) {
                throw new \Exception("购物车不存在");
            }
            $cartList = $cart;
        }
        return $cartList;
    }

    /**
     * 计算购物车金额
     * @param  $cartGoodsList
     * @return int|string
     */
    public function getCartPrice($cartGoodsList)
    {

        $checkedGoodsPrice = 0;
        foreach ($cartGoodsList as $item) {
            $checkedGoodsPrice = bcadd($checkedGoodsPrice, bcmul($item['price'], $item['number'], 2), 2);
        }

        return $checkedGoodsPrice;

    }

    /**
     * 清理购物车记录
     * @param $userId
     * @param $cartId
     * @return false|int
     */
    public function clearCartGoods($userId, $cartId = null)
    {
        if (empty($cartId)) {
            return GoodsCart::where('user_id', $userId)->where('checked', 1)->delete();
        } else {
            return GoodsCart::whereIn('id', $cartId)->where('user_id', $userId)->delete();
        }
    }

}